﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

/** \file ObjectFactory.cs
 */

/**
 * Used to create CollidableObject instances.
 * ObjectFactory can either accept a SpawnPoint,
 * or a Type/TypeEnum with some positioning information,
 * in order to return the appropriate CollidableObject instance.
 */
public static class ObjectFactory
{

    /**
     * Creates the desired CollidableObject instance.
     * @param spawner a SpawnPointer object that identifies the 
     * type of CollidableObject you want 
     * to have created and its coordinates.
     * @return the desired CollidableObject.
     * @see SpawnPoint
     */
    public static CollidableObject get(SpawnPoint spawner)
    {
        CollidableObject target = get(spawner.getType(), spawner.getPosition());
        target.setSpawnPoint(spawner);
        return target;
    }

    /**
     * Creates the desired CollidableObject instance.
     * @param type a TypeEnum object that identifies the 
     * type of CollidableObject you want to have created.
     * @param placement world x,y,z coordinates that the
     * object should be initialized to.
     * @return the desired CollidableObject.
     */
    public static CollidableObject get(TypeEnum type, Vector3 placement)
    {
        switch (type)
        {
            //boundry objects
            case TypeEnum.SideBoundry:
            case TypeEnum.HeightBoundry:
            case TypeEnum.DepthBoundry:
                return new BoundryObject(BoundryObject.Type.getType(type), placement);
            //lightweight objects
            case TypeEnum.Television:
            case TypeEnum.Laptop:
            case TypeEnum.Toaster:
            case TypeEnum.Dish:
            case TypeEnum.Rotor:
            case TypeEnum.Bear:
                return new LightObject(LightObject.Type.getType(type), placement);
            //heavy objects
            case TypeEnum.Helicopter:
            case TypeEnum.Transformer:
            case TypeEnum.Furnace:
            case TypeEnum.Turbine:
                return new HeavyObject(HeavyObject.Type.getType(type), placement);
            //useable objects
            case TypeEnum.Dumpster:
            case TypeEnum.Fridge:
                return new UseableObject(UseableObject.Type.getType(type), placement);
            //drivable objects
            case TypeEnum.Car:
            case TypeEnum.Truck:
                return new DriveableObject(DriveableObject.Type.getType(type), placement);
            //interactive world objects
            case TypeEnum.Door:
            case TypeEnum.Crevice:
                return new InteractiveObject(InteractiveObject.Type.getType(type), placement);
            //breakable world objects
            case TypeEnum.Boulder:
            case TypeEnum.WeakWall:
            case TypeEnum.Tanker:
                return new DestructableObject(DestructableObject.Type.getType(type), placement);
            //quin hero
            case TypeEnum.QuinHero:
                return new QuinHero(QuinHero.Type.getType(type), placement);
            //steve
            case TypeEnum.Steve:
                return new Steve(Steve.Type.getType(type), placement);
            //static world objects
            case TypeEnum.BrickWall:
            case TypeEnum.Window:
            case TypeEnum.BrokenDoor:
            case TypeEnum.Debris:
            case TypeEnum.DebrisPile:
            case TypeEnum.PowerPole:
            case TypeEnum.SewerFloor:
            case TypeEnum.SewerWall:
            case TypeEnum.Street:
            case TypeEnum.DeadHero:
            case TypeEnum.FlatHero:
            case TypeEnum.BurnedHero:
            case TypeEnum.Bench:
            case TypeEnum.LargeDebris2:
            case TypeEnum.LargeDebris3:
            case TypeEnum.LargeDebris4:
            case TypeEnum.Debris2:
            case TypeEnum.Debris3:
            case TypeEnum.Debris4:
            case TypeEnum.Debris5:
            case TypeEnum.Building1:
            case TypeEnum.Building2:
            case TypeEnum.PowerPoleNWires:
            case TypeEnum.Mailbox:
            case TypeEnum.StreetLight:
            case TypeEnum.TrashCan:
            case TypeEnum.OozeContainer:
            case TypeEnum.BrokenPowerPole:
                return new ViewableObject(ViewableObject.Type.getType(type), placement);
            case TypeEnum.Fire:
                return new FireObject(FireObject.Type.getType(type), placement);
            case TypeEnum.Ooze:
                return new OozeObject(OozeObject.Type.getType(type), placement);
            case TypeEnum.DownPower:
                return new ElectricObject(ElectricObject.Type.getType(type), placement);
            case TypeEnum.TNT:
            case TypeEnum.Nuke:
                return new DynamiteObject(DynamiteObject.Type.getType(type), placement);
            case TypeEnum.Teleport:
                return new TeleportObject(TeleportObject.Type.getType(type), placement);
            case TypeEnum.Incubator:
                return new IncubatorObject(IncubatorObject.Type.getType(type), placement);
            case TypeEnum.Professor:
                return new ProfessorObject(ProfessorObject.Type.getType(type), placement);
/*
            //dangerous world objects
            case TypeEnum.Sewage:
            case TypeEnum.Fire:
            case TypeEnum.DownPower:
            case TypeEnum.ElectricPuddle:
                return new DangerousObject(DangerousObject.Type.getType(type), placement);
            //special world objects
            case TypeEnum.Puddle://goes to ElectricPuddle if connected to DownPower
                return new Puddle(type, placement);
            case TypeEnum.Gas:
                return new Gas(type, placement);
            case TypeEnum.Professor:
                return new Professor(type, placement);
            case TypeEnum.TNT:
                return new TNT(type, placement);
*/
            case TypeEnum.Hero:
                return new Hero(ViewableObject.Type.getType(type), placement);
            //triggers
            case TypeEnum.BoulderTrigger:
                return new SpawnTrigger(SpawnTrigger.Type.getType(type), placement);
            case TypeEnum.LoadingZone:
                return new GoalTrigger(GoalTrigger.Type.getType(type), placement);
        }
        return null;
    }

    /**
     * Creates the desired CollidableObject instance.
     * @param type a CollidableObject.Type object that 
     * identifies the 
     * type of CollidableObject you want to have created.
     * @param placement world x,y,z coordinates for where this
     * object should be placed
     * @return the desired CollidableObject.
     */
    public static CollidableObject get(CollidableObject.Type type, Vector3 placement)
    {
        switch (type.myType)
        {
            //boundry objects
            case TypeEnum.SideBoundry:
            case TypeEnum.HeightBoundry:
            case TypeEnum.DepthBoundry:
                return new BoundryObject((BoundryObject.Type)type, placement);
            //lightweight objects
            case TypeEnum.Television:
            case TypeEnum.Laptop:
            case TypeEnum.Toaster:
            case TypeEnum.Dish:
            case TypeEnum.Rotor:
            case TypeEnum.Bear:
                return new LightObject((LightObject.Type)type, placement);
            //heavy objects
            case TypeEnum.Helicopter:
            case TypeEnum.Transformer:
            case TypeEnum.Furnace:
            case TypeEnum.Turbine:
                return new HeavyObject((HeavyObject.Type)type, placement);
            //useable objects
            case TypeEnum.Dumpster:
            case TypeEnum.Fridge:
                return new UseableObject((UseableObject.Type)type, placement);
            //drivable objects
            case TypeEnum.Car:
            case TypeEnum.Truck:
                return new DriveableObject((DriveableObject.Type)type, placement);
            //interactive world objects
            case TypeEnum.Door:
            case TypeEnum.Crevice:
                return new InteractiveObject((InteractiveObject.Type)type, placement);
            //breakable world objects
            case TypeEnum.Boulder:
            case TypeEnum.WeakWall:
            case TypeEnum.Tanker:
                return new DestructableObject((DestructableObject.Type)type, placement);
            //quin hero
            case TypeEnum.QuinHero:
                return new QuinHero((QuinHero.Type)type, placement);
            //steve
            case TypeEnum.Steve:
                return new Steve((Steve.Type)type, placement);
            //static world objects
            case TypeEnum.BrickWall:
            case TypeEnum.Window:
            case TypeEnum.BrokenDoor:
            case TypeEnum.Debris:
            case TypeEnum.DebrisPile:
            case TypeEnum.PowerPole:
            case TypeEnum.SewerFloor:
            case TypeEnum.SewerWall:
            case TypeEnum.Street:
            case TypeEnum.DeadHero:
            case TypeEnum.FlatHero:
            case TypeEnum.BurnedHero:
            case TypeEnum.Bench:
            case TypeEnum.LargeDebris2:
            case TypeEnum.LargeDebris3:
            case TypeEnum.LargeDebris4:
            case TypeEnum.Debris2:
            case TypeEnum.Debris3:
            case TypeEnum.Debris4:
            case TypeEnum.Debris5:
            case TypeEnum.Building1:
            case TypeEnum.Building2:
            case TypeEnum.PowerPoleNWires:
            case TypeEnum.Mailbox:
            case TypeEnum.StreetLight:
            case TypeEnum.TrashCan:
            case TypeEnum.OozeContainer:
            case TypeEnum.BrokenPowerPole:
                return new ViewableObject((ViewableObject.Type)type, placement);
            case TypeEnum.Fire:
                return new FireObject((FireObject.Type)type, placement);
            case TypeEnum.Ooze:
                return new OozeObject((OozeObject.Type)type, placement);
            case TypeEnum.DownPower:
                return new ElectricObject((ElectricObject.Type)type, placement);
            case TypeEnum.TNT:
            case TypeEnum.Nuke:
                return new DynamiteObject((DynamiteObject.Type)type, placement);
            case TypeEnum.Teleport:
                return new TeleportObject((TeleportObject.Type)type, placement);
            case TypeEnum.Incubator:
                return new IncubatorObject((IncubatorObject.Type)type, placement);
            case TypeEnum.Professor:
                return new ProfessorObject((ProfessorObject.Type)type, placement);
/*
            //dangerous world objects
            case TypeEnum.Sewage:
            case TypeEnum.Fire:
            case TypeEnum.DownPower:
            case TypeEnum.ElectricPuddle:
                return new DangerousObject(type, placement);
            //special world objects
            case TypeEnum.Puddle://goes to ElectricPuddle if connected to DownPower
                return new Puddle(type, placement);
            case TypeEnum.Gas:
                return new Gas(type, placement);
            case TypeEnum.Professor:
                return new Professor(type, placement);
            case TypeEnum.Incubator:
                return new Incubator(type, placement);
            case TypeEnum.TNT:
                return new TNT(type, placement);
 */
            case TypeEnum.Hero:
                return new Hero((ViewableObject.Type)type, placement);
            //triggers
            case TypeEnum.BoulderTrigger:
                return new SpawnTrigger((SpawnTrigger.Type)type, placement);
            case TypeEnum.LoadingZone:
                return new GoalTrigger((GoalTrigger.Type)type, placement);
        }
        return null;
    }

    /**
     * specifies a specific type of CollidableObject.
     * This enum stores as a short in order to save space
     * and allow using this enum to be an efficient way 
     * to specify a specific CollidableObject.
     */
    public enum TypeEnum : short
    {
        //boundry objects
        SideBoundry, HeightBoundry, DepthBoundry,
        //lightweight objects
        Television, Laptop, Toaster, Dish, Rotor, Bear,
        //heavy objects
        Helicopter, Transformer, Furnace, Turbine,
        //useable objects
        Dumpster, Fridge,
        //drivable objects
        Car, Truck,
        //interactive world objects
        Door, Crevice,
        //breakable world objects
        Boulder, WeakWall, Tanker, QuinHero,
        //static world objects
        BrickWall, Window, BrokenDoor, Debris, DebrisPile, PowerPole, BrokenPowerPole,
        SewerWall, SewerFloor, Street, DeadHero, FlatHero, BurnedHero, Bench, LargeDebris2,
        LargeDebris3, LargeDebris4, Debris2, Debris3, Debris4, Debris5,
        PowerPoleNWires, Mailbox, StreetLight, TrashCan, OozeContainer,
        Building1, Building2,
        //dangerous world objects
        Ooze, Sewage, Fire, DownPower, ElectricPuddle,
        //special world objects
        Puddle,//goes to ElectricPuddle if connected to DownPower
        Gas,//goes to Fire if connecter to Fire or DownPower=
        Hero,
        Steve,
        Professor,
        Incubator,
        TNT, Nuke,
        Teleport,
        //triggers
        BoulderTrigger, LoadingZone
    } 
}
